#from src.wyf.gmid.opamps.modules.circuits.FullyDifferentialAmp import ful_dif_amp
import pytest
from pyted import *
from .HighPerformance_FDA_generator3 import HP_FullyDifferentialAmp
from .HighPerformance_FDA_generator3_for_opt import HP_FullyDifferentialAmp_for_opt
from pyted.modules import VCVS, C, Capacitor, I, Mosfet, R, V, X, VSource
from pyted.modules import Vsin, Vdc
from modules.components import (
    NMOS,
    PMOS,
    MomCap,
    MosGrid,
    PairedMosfet,
    RpolySingle,
)
from .HighPerformance_FDA import ful_dif_amp


def test_FDA():
    # from wyf.mylib.fully_differential_amp_generator import \
    #     FullyDifferentialAmp

    specs = {
        "VDD": 1.2,
        "VCM": 0.6,
        "GBW": 100e6,
        "GAIN": 80,
        "SR": 30,
        "Iref": 20e-6,
        "NOISE": 1,
        "CLoad":3e-12
    }
    result = HP_FullyDifferentialAmp(specs).test(stage="pre", OTAtype="dido")
    # corners=["tt"], 
    debug(result)
    
def test_lvs():
    # from wyf.mylib.fully_differential_amp_generator import \
    #     FullyDifferentialAmp

    specs = {
        "VDD": 1.2,
        "VCM": 0.6,
        "GBW": 100e6,
        "GAIN": 80,
        "SR": 30,
        "Iref": 20e-6,
        "NOISE": 60e-9,
        "CLoad":3e-12
    }
    result = HP_FullyDifferentialAmp(specs).lvs()
    # corners=["tt"], 
   
def test_opt():
    from frontend.tester import CombinedTester
    from tedhub.circuit.testers import OTATester
    from taco.ea import NSGA_II, DE
    from benchmarks.tracer import Tracer
    from pyted import setenv

    specs = {
        "VDD": 1.2,
        "VCM": 0.6,
        "GBW": 100e6,
        "GAIN": 80,
        "SR": 30,
        "Iref": 20e-6,
        "NOISE": 1,
        "CLoad":3e-12
    }
    
    
    dut = HP_FullyDifferentialAmp_for_opt(specs)
    ota_tester: OTATester = dut.test()
    # dut.to_fig(name="initial")
    tester = CombinedTester(
        [
            ota_tester.gainTester,
            ota_tester.noiseTester,
            ota_tester.DCTester,
            ota_tester.psrrTester,
            ota_tester.cmrrTester,
            ota_tester.srTester,
        ]
    )

    def problem(tester: OTATester):
        from pyted.taco import Problem

        gain = tester["gain"]
        bw = tester["bw"]
        pm = tester["pm"]
        ugb = tester["ugb"]
        power = tester["power"]
        gainDB = gain.db()
        srp, srn = tester["SRp"], tester["SRn"]

        debug(
            "\n"
            + bcolors.render(
                ", ".join(
                    [
                        f"gain = {gainDB:.2f}dB",
                        f"bw = {bw/1e6:.4f}Mhz",
                        f"ugb = {ugb/1e6:.4f}Mhz",
                        f"pm = {pm:.2f}",
                        f"srp={srp*1e-6:2f}V/us",
                        f"srn={srn*1e-6:2f}V/us",
                        f"power = {power*1e3:.2e}mW",
                    ]
                ),
                color="yellow",
            )
        )
        return Problem(
            objective=pm.maximize().rename("SRp"),
            constraint=(
                power.lt(1.99e-3).rename("Power"),
                ugb.gt(101e6).rename("UGB"),
                gainDB.gt(81).rename("Av"),
                pm.gt(61).rename("PM"),
                pm.lt(90).rename("PM"),
                srp.gt(30e6).rename("SRp"),
                srn.lt(-30e6).rename("SRn"),
            ),
        )

    configs = {
        "pop_size": 40,
        "maxgen": 50,
        "ref_point": 35,
    }

    opt = tester.optimize(
        problem=problem,
        optimizer=DE,
        tracer=Tracer,
        **configs,
    )

    res = opt.solve()
    if res.get("success"):
        dut.update_variables(res=res)
        dut.test(name="Optimization")
        dut.report(name="Opt")


